package com.gitee.wsl.compose.use.from

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import com.gitee.wsl.compose.base.Ref
import com.gitee.wsl.compose.base.createContext
import com.gitee.wsl.compose.base.useContext
import com.gitee.wsl.compose.use._useState
import com.gitee.wsl.compose.use.useBoolean
import com.gitee.wsl.compose.use.useCreation
import com.gitee.wsl.compose.use.useMap
import com.gitee.wsl.compose.use.useState
import com.gitee.wsl.compose.use.coroutines.useEffect
import com.gitee.wsl.compose.use.event.useEventPublish
import com.gitee.wsl.compose.use.event.useEventSubscribe
import com.gitee.wsl.transform.validator.Validator
import kotlin.reflect.KClass


/*
  Description: Headless Form Component
  Author: Junerver
  Date: 2024/3/25-8:11
  Email: junerver@gmail.com
  Version: v1.0
*/

internal val FormContext by lazy { createContext(FormInstance()) }

/*
  Description:
  Author: Junerver
  Date: 2024/3/25-10:06
  Email: junerver@gmail.com
  Version: v1.0
*/
object Form

@Composable
fun Form.useForm(): FormInstance = remember { FormInstance() }

/**
 * 使用这个 Hook 你可以在 [FormScope] 外直接获取一个字段的内容**状态**
 *
 * Using this Hook you can directly obtain the content [State] of a field
 * outside [FormScope]
 *
 * @param fieldName the form field to be tracked
 * @param formInstance form controller instance
 * @param T
 * @return
 */
@Composable
fun <T> Form.useWatch(fieldName: String, formInstance: FormInstance): State<T?> {
    val state = _useState<T?>(null)
    useEventSubscribe<T?>(fieldName.genFormFieldKey(formInstance)) { value ->
        state.value = value
    }
    return state
}

/**
 * 方便子组件获取到 [FormInstance]
 *
 * Convenient for subcomponents to obtain [FormInstance]
 *
 * @return
 */
@Composable
fun Form.useFormInstance(): FormInstance = useContext(context = FormContext)


/**
 * Headless Form Component
 *
 * @param formInstance
 * @param content
 * @receiver
 */
@Composable
fun Form(formInstance: FormInstance = Form.useForm(), content: @Composable FormScope.() -> Unit) {
    val formRef = useCreation { FormRef() }
    formInstance.apply { this.formRef = formRef }
    FormContext.Provider(formInstance) {
        FormScope.getInstance(formRef, formInstance).content()
    }
}

/**
 * Form Component scope
 *
 * @constructor Create empty Form scope
 * @property formRefRef
 * @property formInstance
 */
class FormScope private constructor(
    private val formRefRef: Ref<FormRef>,
    private val formInstance: FormInstance,
) {

    /**
     * 表单字段容器组件
     *
     * FormItem Component
     *
     * @param name
     * @param validators
     * @param content 子组件函数，通过参数提供字段状态、是否通过校验、错误信息列表
     * @param T
     * @receiver
     */
    @Composable
    fun <T:Any> FormItem(
        name: String,
        validators: Validator<T?,*>,
        content: @Composable (Triple<MutableState<T?>, Boolean, List<String>>) -> Unit,
    ) {
        val fieldState = _useState<T?>(default = null)
        val (validate, _, set) = useBoolean()
        val errMsg = useMap<KClass<*>, String>()
        val currentFormRef: FormRef = formRefRef.current
        @Suppress("UNCHECKED_CAST")
        currentFormRef.formFieldMap[name] = fieldState as MutableState<Any?>
        val publish = useEventPublish<T?>(name.genFormFieldKey(formInstance))
        useEffect(fieldState) {
            currentFormRef.formOperationCount.longValue += 1
            val value = fieldState.value as T?

            publish(value)

            /*fun Validator<T?>.pass(): Boolean {
                errMsg.remove(this::class)
                return true
            }

            fun Validator<T?>.fail(): Boolean {
                errMsg[this::class] = this.message
                return false
            }*/

            //val fieldValue: Any? = fieldState.value

            /*val isValidate =(validators as Array<Validator>).validateField(fieldValue, pass = Validator::pass, fail = Validator::fail)*/

//            fun Validator<T?,*>.pass():Unit {
//                errMsg.remove(this::class)
//            }
//
//            fun Validator<T?,*>.fail(message:String):Unit {
//                errMsg[this::class] = message
//            }

            val isValidate = validators.validate(value)

            set(isValidate)
            currentFormRef.formFieldValidationMap[name] = isValidate
        }

        useEffect(errMsg) {
            currentFormRef.formFieldErrorMessagesMap[name] = errMsg.values.toList()
        }
        content(Triple(fieldState, validate, errMsg.values.toList()))
    }

    /**
     * 获取是否验证通过的**状态**，
     *
     * Get the [State] of whether the verification is passed or not
     *
     * @return
     */
    @Composable
    fun FormInstance._isValidated(): State<Boolean> {
        val counter by formRef.current.formOperationCount
        return useState(counter) {
            isValidated()
        }
    }

    companion object {
        internal fun getInstance(ref: Ref<FormRef>, formInstance: FormInstance) = FormScope(ref, formInstance)
    }
}

internal const val KEY_PREFIX = "HOOK_INTERNAL_"
private const val FORM_KEY_PREFIX = "${KEY_PREFIX}FORM_FIELD_"

internal fun String.genFormFieldKey(formInstance: FormInstance) = "${FORM_KEY_PREFIX}${formInstance}_$this"
